﻿// Copyright 2001-2010 - Active Up SPRLU (http://www.agilecomponents.com)
//
// Data Connection Suite is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.

// Data Connection Suite is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
// for more details.

// You should have received a copy of the GNU General Public License along with
// Data Connection Suite. If not, see http://www.gnu.org/licenses/.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.Sql;
using System.Data.SqlClient;
using System.Data.Common;

namespace AgileComponents.DataConnection
{
    /// <summary>
    /// 
    /// </summary>
    public partial class SqlServerDataConnectionControl : DataConnectionControl
    {
        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="SqlServerDataConnectionControl"/> class.
        /// </summary>
        public SqlServerDataConnectionControl()
        {
            InitializeComponent();

            this.Builder = new SqlConnectionStringBuilder();

            this.useWindowsAuthenticationRadioButton.PerformClick();
        }

        #endregion

        #region Event Handlers

        /// <summary>
        /// Handles the Click event of the refreshButton control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void refreshButton_Click(object sender, EventArgs e)
        {
            this.RefreshInstances();
        }

        /// <summary>
        /// Handles the Click event of the databasesComboBox control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void databasesComboBox_Click(object sender, EventArgs e)
        {
            if (!DatabaseListCreated && !DatabaseListCreating)
                this.GetDatabase();
        }

        /// <summary>
        /// Handles the CheckedChanged event of the selectOrEnterADatabaseNRadioButton control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void selectOrEnterADatabaseNRadioButton_CheckedChanged(object sender, EventArgs e)
        {
            this.databasesComboBox.Enabled = true;

            this.databaseFileTextBox.Enabled = false;
            this.logicalNameLabel.Enabled = false;
            this.browseButton.Enabled = false;
            this.logicalNameTextBox.Enabled = false;

        }

        /// <summary>
        /// Handles the CheckedChanged event of the attachADatabaseFileRadioButton control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void attachADatabaseFileRadioButton_CheckedChanged(object sender, EventArgs e)
        {
            this.databasesComboBox.Enabled = false;

            this.databaseFileTextBox.Enabled = true;
            this.logicalNameLabel.Enabled = true;
            this.browseButton.Enabled = true;
            this.logicalNameTextBox.Enabled = true;
        }

        /// <summary>
        /// Handles the KeyUp event of the serverNamesComboBox control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.KeyEventArgs"/> instance containing the event data.</param>
        private void serverNamesComboBox_KeyUp(object sender, KeyEventArgs e)
        {
            DatabaseListCreating = DatabaseListCreated = false;
            if (!string.IsNullOrEmpty(this.serverNamesComboBox.Text) &&
                this.connectToDatabaseGroupBox.Enabled == false)
            {
                this.connectToDatabaseGroupBox.Enabled = true;
                this.selectOrEnterADatabaseNRadioButton.PerformClick();
            }
        }

        /// <summary>
        /// Handles the Click event of the testConnectionButton control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void testConnectionButton_Click(object sender, EventArgs e)
        {
            this.TestConnectionString(this.serverNamesComboBox.Text);
        }

        /// <summary>
        /// Handles the CheckedChanged event of the useWindowsAuthenticationRadioButton control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void useWindowsAuthenticationRadioButton_CheckedChanged(object sender, EventArgs e)
        {
            this.usernameLabel.Enabled = false;
            this.usernameTextBox.Enabled = false;
            this.usernameTextBox.Text = string.Empty;
            this.passwordLabel.Enabled = false;
            this.passwordTextBox.Enabled = false;
            this.passwordTextBox.Text = string.Empty;
            this.saveMyPasswordCheckBox.Checked = false;
            this.saveMyPasswordCheckBox.Enabled = false;

            this.RaiseDataConnectionChanged();
        }

        /// <summary>
        /// Handles the CheckedChanged event of the useSqlServerAuthenticationRadioButton control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void useSqlServerAuthenticationRadioButton_CheckedChanged(object sender, EventArgs e)
        {
            this.usernameLabel.Enabled = true;
            this.usernameTextBox.Enabled = true;
            this.usernameTextBox.Text = string.Empty;
            this.passwordLabel.Enabled = true;
            this.passwordTextBox.Enabled = true;
            this.passwordTextBox.Text = string.Empty;
            this.saveMyPasswordCheckBox.Checked = false;
            this.saveMyPasswordCheckBox.Enabled = true;

            this.RaiseDataConnectionChanged();
        }

        /// <summary>
        /// Handles the SelectedIndexChanged event of the serverNamesComboBox control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void serverNamesComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            DatabaseListCreated = DatabaseListCreating = false;
            this.databasesComboBox.Items.Clear();
            this.connectToDatabaseGroupBox.Enabled = true;
            this.selectOrEnterADatabaseNRadioButton.PerformClick();
        }

        /// <summary>
        /// Handles the TextUpdate event of the serverNamesComboBox control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void serverNamesComboBox_TextUpdate(object sender, EventArgs e)
        {
            if (DatabaseListCreated)
            {
                this.databasesComboBox.Items.Clear();
                DatabaseListCreated = false;
            }

            this.RaiseDataConnectionChanged();
        }

        /// <summary>
        /// Handles the TextChanged event of the usernameTextBox control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void usernameTextBox_TextChanged(object sender, EventArgs e)
        {
            this.RaiseDataConnectionChanged();
        }

        /// <summary>
        /// Handles the TextChanged event of the passwordTextBox control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void passwordTextBox_TextChanged(object sender, EventArgs e)
        {
            this.RaiseDataConnectionChanged();
        }

        /// <summary>
        /// Handles the TextChanged event of the databasesComboBox control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void databasesComboBox_TextChanged(object sender, EventArgs e)
        {
            this.RaiseDataConnectionChanged();
        }

        /// <summary>
        /// Handles the TextChanged event of the databaseFileTextBox control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void databaseFileTextBox_TextChanged(object sender, EventArgs e)
        {
            this.RaiseDataConnectionChanged();
        }

        /// <summary>
        /// Handles the TextChanged event of the logicalNameTextBox control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void logicalNameTextBox_TextChanged(object sender, EventArgs e)
        {
            this.RaiseDataConnectionChanged();
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// Refreshes the instances.
        /// </summary>
        private void RefreshInstances()
        {
            SqlDataSourceEnumerator instance = SqlDataSourceEnumerator.Instance;
            System.Data.DataTable table = instance.GetDataSources();

            this.serverNamesComboBox.Items.Clear();
            foreach (System.Data.DataRow row in table.Rows)
                this.serverNamesComboBox.Items.Add(row["ServerName"]);
        }
       
        /// <summary>
        /// Gets the database.
        /// </summary>
        private void GetDatabase()
        {
            try
            {
                this.databasesComboBox.Items.Clear();
                this.databasesComboBox.Items.Add("Please wait while loading available databases...");
                DataTable tables = new DataTable("Tables");
                using (IDbConnection connection = this.GetConnection())
                {
                    IDbCommand command = connection.CreateCommand();
                    command.CommandText = "SELECT * FROM sys.Databases";
                    connection.Open();
                    tables.Load(command.ExecuteReader(CommandBehavior.CloseConnection));
                }
                this.databasesComboBox.Items.Clear();
                foreach (DataRow row in tables.Rows)
                    this.databasesComboBox.Items.Add(row[0].ToString());
            }
            catch (SqlException)
            {
                this.databasesComboBox.Items.Clear();
                this.databasesComboBox.Items.Add("Connection error. Check server & credentials");
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error while loading available databases: " + ex.ToString());
            }
            finally
            {
                DatabaseListCreating = false;
            }
        }

        /// <summary>
        /// Handles the Click event of the advancedButton control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void advancedButton_Click(object sender, EventArgs e)
        {
            ConnectionStringPropertiesDialog dialog = new ConnectionStringPropertiesDialog(this.Builder);
            dialog.ShowDialog();

            PopulateForm();
        }

        #endregion

        #region Implementation

        /// <summary>
        /// Gets the connection string.
        /// </summary>
        /// <returns></returns>
        public override IDbConnection GetConnection()
        {
            return new SqlConnection(this.ConnectionString);
        }

        /// <summary>
        /// Gets or sets the connection string.
        /// </summary>
        /// <value>The connection string.</value>
        public override string ConnectionString
        {
            get
            {
                PopulateBuilder();
                return base.ConnectionString;
            }
            set
            {
                base.ConnectionString = value;
                PopulateForm();
            }
        }
       
        /// <summary>
        /// Populates the builder.
        /// </summary>
        private void PopulateBuilder()
        {
            SqlConnectionStringBuilder builder = (SqlConnectionStringBuilder)this.Builder;

            builder.DataSource = this.serverNamesComboBox.Text;

            builder.IntegratedSecurity = this.useWindowsAuthenticationRadioButton.Checked;

            if (!string.IsNullOrEmpty(this.usernameTextBox.Text))
                builder.UserID = this.usernameTextBox.Text;

            if (!string.IsNullOrEmpty(this.passwordTextBox.Text))
                builder.Password = this.passwordTextBox.Text;

            if (!string.IsNullOrEmpty(this.databasesComboBox.Text))
                builder.InitialCatalog = this.databasesComboBox.Text;

            if (!string.IsNullOrEmpty(this.databaseFileTextBox.Text))
                builder.AttachDBFilename = this.databaseFileTextBox.Text;

            if (!string.IsNullOrEmpty(this.logicalNameTextBox.Text))
                builder.ApplicationName = this.logicalNameTextBox.Text;
        }

        /// <summary>
        /// Populates the form.
        /// </summary>
        private void PopulateForm()
        {
            SqlConnectionStringBuilder builder = (SqlConnectionStringBuilder)this.Builder;

            this.serverNamesComboBox.Text = builder.DataSource;

            this.useWindowsAuthenticationRadioButton.Checked = builder.IntegratedSecurity;
            if (builder.IntegratedSecurity)
                this.useWindowsAuthenticationRadioButton.PerformClick();

            this.usernameTextBox.Text = builder.UserID;

            this.passwordTextBox.Text = builder.Password;

            this.databasesComboBox.Text = builder.InitialCatalog;

            this.databaseFileTextBox.Text = builder.AttachDBFilename;

            this.logicalNameTextBox.Text = builder.ApplicationName = this.logicalNameTextBox.Text;
        }

        #endregion
    }
}
